package com.scale.service.voice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.voice.dto.CreateVoiceTaskDTO;
import com.example.voice.entity.VoiceProcessingTasks;
import com.example.voice.enums.TaskStatus;
import com.scale.service.voice.mapper.VoiceProcessingTasksMapper;
import com.example.voice.vo.VoiceTaskVO;
import com.scale.service.ai.service.AIModelService;
import com.scale.service.character.service.AiCharactersService;
import com.example.character.entity.AiCharacters;
import com.scale.service.voice.service.StreamAsrService;
import com.scale.service.voice.service.StreamTtsService;
import com.scale.service.voice.service.TaskProgressService;
import com.scale.service.voice.service.VoiceTaskService;
import com.scale.service.conversation.service.MessagesService;
import com.scale.service.conversation.service.ConversationsService;
import com.scale.service.voice.service.VoiceFileStorageService;
import com.scale.service.voice.service.VoiceTaskWebSocketHandler;
import com.example.conversation.entity.Messages;
import com.example.conversation.entity.Conversations;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.UUID;

/**
 * 语音任务管理服务实现类
 * @author crp
 * @since 2025-01-26
 */
@Service
public class VoiceTaskServiceImpl implements VoiceTaskService {
    
    @Autowired
    private VoiceProcessingTasksMapper voiceTaskMapper;
    
    @Autowired
    private StreamAsrService streamAsrService;
    
    @Autowired
    private AIModelService aiModelService;
    
    @Autowired
    private AiCharactersService aiCharactersService;
    
    @Autowired
    private StreamTtsService streamTtsService;
    
    @Autowired
    private TaskProgressService taskProgressService;
    
    @Autowired
    private MessagesService messagesService;
    
    @Autowired
    private ConversationsService conversationsService;
    
    @Autowired 
    private VoiceFileStorageService voiceFileStorageService;
    
    @Autowired
    private VoiceTaskWebSocketHandler webSocketHandler;
    
    @Value("${server.port:8080}")
    private String serverPort;
    
    @Override
    public VoiceTaskVO createTask(CreateVoiceTaskDTO dto) {
        // 1. 生成任务ID
        String taskId = generateTaskId();
        System.out.println("创建语音处理任务: taskId=" + taskId);
        
        // 2. 先保存用户录音文件
        String userVoiceUrl = null;
        try {
            userVoiceUrl = saveUserAudioFile(dto.getAudioData(), dto.getFormat(), dto.getUserId());
            System.out.println("✅ 用户录音文件已保存: " + userVoiceUrl);
        } catch (Exception e) {
            System.err.println("❌ 保存用户录音文件失败: " + e.getMessage());
            // 继续处理，不影响主流程
        }
        
        // 3. 保存任务到数据库
        VoiceProcessingTasks task = new VoiceProcessingTasks();
        task.setTaskId(taskId);
        task.setUserId(dto.getUserId());
        task.setCharacterId(dto.getCharacterId());
        task.setConversationId(dto.getConversationId());
        task.setAudioFormat(dto.getFormat());
        task.setLanguage(dto.getLanguage());
        task.setUserVoiceUrl(userVoiceUrl); // 设置用户语音文件URL
        task.setStatus(TaskStatus.PENDING.getCode());
        task.setProgress(0);
        task.setCreatedAt(LocalDateTime.now());
        task.setUpdatedAt(LocalDateTime.now());
        
        int insertResult = voiceTaskMapper.insert(task);
        System.out.println("数据库插入结果: " + insertResult + ", taskId=" + taskId + ", userVoiceUrl=" + userVoiceUrl);
        
        // 4. 异步处理任务
        System.out.println("开始异步处理任务: " + taskId);
        asyncProcessTask(taskId, dto.getAudioData());
        
        return buildTaskVO(task);
    }
    
    @Override
    @Async
    public void asyncProcessTask(String taskId, String audioData) {
        System.out.println("异步处理任务开始: " + taskId);
        
        // 🔧 等待用户WebSocket连接建立
        VoiceProcessingTasks task = getTaskByTaskId(taskId);
        if (task == null) {
            System.out.println("任务不存在: " + taskId);
            return;
        }
        
        String userId = String.valueOf(task.getUserId());
        if (!waitForWebSocketConnection(taskId, userId)) {
            System.err.println("⚠️ 用户WebSocket连接超时，继续处理任务（但无法发送实时更新）: taskId=" + taskId + ", userId=" + userId);
        }
        
        try {
            // task已经在上面获取过了，直接使用
            
            System.out.println("开始ASR处理: " + taskId);
            // 更新任务状态为处理中
            updateTaskStatus(taskId, TaskStatus.PROCESSING, 0, "ASR");
            
            // 1. 流式ASR处理
            String recognizedText = streamAsrService.processAsrStream(taskId, audioData);
            task.setRecognizedText(recognizedText);
            System.out.println("ASR完成，识别文本: " + recognizedText);
            updateTaskStatus(taskId, TaskStatus.PROCESSING, 30, "AI");
            
            // 2. AI对话生成
            System.out.println("开始AI对话生成: " + taskId);
            AiCharacters character = aiCharactersService.getById(task.getCharacterId());
            String conversationHistory = aiModelService.buildConversationContext(
                task.getCharacterId(), task.getUserId(), recognizedText);
            String aiReply = aiModelService.getAIReply(character, recognizedText, 
                conversationHistory, task.getUserId());
            task.setAiReply(aiReply);
            System.out.println("AI对话完成，回复: " + aiReply);
            updateTaskStatus(taskId, TaskStatus.PROCESSING, 60, "TTS");
            
            // 3. 流式TTS处理
            System.out.println("开始TTS处理: " + taskId);
            String voiceUrl = streamTtsService.processTtsStream(taskId, aiReply, 
                "female", task.getLanguage());
            task.setVoiceUrl(voiceUrl);
            System.out.println("TTS完成，语音URL: " + voiceUrl);
            
            // 4. 更新任务完成状态
            updateTaskStatus(taskId, TaskStatus.COMPLETED, 100, "STORAGE");
            
            // 5. 更新数据库中的最终结果
            VoiceProcessingTasks finalTask = getTaskByTaskId(taskId);
            if (finalTask != null) {
                finalTask.setRecognizedText(recognizedText);
                finalTask.setAiReply(aiReply);
                finalTask.setVoiceUrl(voiceUrl);
                finalTask.setStatus(TaskStatus.COMPLETED.getCode());
                finalTask.setProgress(100);
                finalTask.setCurrentStep("STORAGE");
                finalTask.setUpdatedAt(LocalDateTime.now());
                voiceTaskMapper.updateById(finalTask);
                System.out.println("数据库最终更新完成: " + taskId);
            }
            
            // 6. 保存消息到数据库
            try {
                saveMessagesToDatabase(task, recognizedText, aiReply, voiceUrl);
                System.out.println("✅ 消息保存到数据库成功: " + taskId);
            } catch (Exception e) {
                System.err.println("❌ 保存消息到messages表失败: " + e.getMessage());
                e.printStackTrace();
                // 不影响主流程，继续执行
            }
            
            // 7. 发送完成消息
            taskProgressService.sendTaskCompleted(taskId, recognizedText, aiReply, voiceUrl);
            System.out.println("任务处理完成: " + taskId);
            
        } catch (Exception e) {
            System.err.println("任务处理失败: " + taskId + ", 错误: " + e.getMessage());
            e.printStackTrace();
            updateTaskStatus(taskId, TaskStatus.FAILED, 0, "ERROR");
            VoiceProcessingTasks errorTask = getTaskByTaskId(taskId);
            if (errorTask != null) {
                errorTask.setErrorMessage(e.getMessage());
                voiceTaskMapper.updateById(errorTask);
            }
            taskProgressService.sendTaskFailed(taskId, "PROCESSING_FAILED", e.getMessage());
        }
    }
    
    @Override
    public VoiceTaskVO getTaskStatus(String taskId) {
        VoiceProcessingTasks taskForStatus = getTaskByTaskId(taskId);
        if (taskForStatus == null) {
            return null;
        }
        return buildTaskVO(taskForStatus);
    }
    
    @Override
    public boolean cancelTask(String taskId) {
        VoiceProcessingTasks task = getTaskByTaskId(taskId);
        if (task != null && !TaskStatus.COMPLETED.getCode().equals(task.getStatus()) 
            && !TaskStatus.FAILED.getCode().equals(task.getStatus())) {
            task.setStatus(TaskStatus.FAILED.getCode());
            task.setErrorMessage("用户取消任务");
            task.setUpdatedAt(LocalDateTime.now());
            voiceTaskMapper.updateById(task);
            return true;
        }
        return false;
    }
    
    private String generateTaskId() {
        return "task_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8);
    }
    
    private VoiceProcessingTasks getTaskByTaskId(String taskId) {
        return voiceTaskMapper.selectOne(
            new QueryWrapper<VoiceProcessingTasks>().eq("task_id", taskId)
        );
    }
    
    private void updateTaskStatus(String taskId, TaskStatus status, Integer progress, String currentStep) {
        VoiceProcessingTasks task = getTaskByTaskId(taskId);
        if (task != null) {
            task.setStatus(status.getCode());
            task.setProgress(progress);
            task.setCurrentStep(currentStep);
            task.setUpdatedAt(LocalDateTime.now());
            voiceTaskMapper.updateById(task);
        }
    }
    
    private VoiceTaskVO buildTaskVO(VoiceProcessingTasks task) {
        VoiceTaskVO vo = new VoiceTaskVO();
        BeanUtils.copyProperties(task, vo);
        vo.setEstimatedTime(15); // 预估15秒
        // 🔧 修改为按用户管理的WebSocket URL
        vo.setWsUrl("ws://localhost:" + serverPort + "/ws/voice-task/user/" + task.getUserId());
        return vo;
    }
    
    /**
     * 保存消息到数据库
     */
    private void saveMessagesToDatabase(VoiceProcessingTasks task, String recognizedText, String aiReply, String voiceUrl) {
        try {
            // 1. 确保有conversation_id
            Long conversationId = task.getConversationId();
            if (conversationId == null) {
                // 如果没有会话ID，创建或获取一个默认会话
                Conversations conversation = conversationsService.createOrGetConversation(task.getUserId(), task.getCharacterId());
                if (conversation != null) {
                    conversationId = conversation.getId();
                    // 🔧 修复状态重置bug：只更新conversation_id字段，不影响其他状态
                    VoiceProcessingTasks updateConversationTask = new VoiceProcessingTasks();
                    updateConversationTask.setId(task.getId());
                    updateConversationTask.setConversationId(conversationId);
                    updateConversationTask.setUpdatedAt(LocalDateTime.now());
                    voiceTaskMapper.updateById(updateConversationTask);
                    task.setConversationId(conversationId); // 同步内存中的对象
                    System.out.println("✅ 为任务创建了新的会话ID: " + conversationId);
                } else {
                    throw new RuntimeException("无法创建会话记录");
                }
            }
            
            // 2. 保存用户消息（语音输入）
            Messages userMessage = new Messages();
            userMessage.setConversationId(conversationId);
            userMessage.setSenderType(1); // 1-用户
            userMessage.setContent(recognizedText);
            userMessage.setContentType("voice");
            userMessage.setVoiceUrl(task.getUserVoiceUrl()); // 用户语音URL
            userMessage.setCreatedAt(LocalDateTime.now());
            
            boolean userMessageSaved = messagesService.save(userMessage);
            System.out.println("用户消息保存结果: " + userMessageSaved);
            
            // 3. 保存AI回复消息
            Messages aiMessage = new Messages();
            aiMessage.setConversationId(conversationId);
            aiMessage.setSenderType(2); // 2-AI角色
            aiMessage.setContent(aiReply);
            aiMessage.setContentType("voice");
            aiMessage.setVoiceUrl(voiceUrl); // AI语音URL
            aiMessage.setAiResponseTime(1500); // 模拟响应时间
            aiMessage.setCreatedAt(LocalDateTime.now());
            
            boolean aiMessageSaved = messagesService.save(aiMessage);
            System.out.println("AI消息保存结果: " + aiMessageSaved);
            
            // 4. 更新会话统计
            Conversations conversation = conversationsService.getById(conversationId);
            if (conversation != null) {
                conversation.setTotalMessages((conversation.getTotalMessages() == null ? 0 : conversation.getTotalMessages()) + 2);
                conversation.setUpdatedAt(LocalDateTime.now());
                conversationsService.updateById(conversation);
                System.out.println("✅ 会话统计已更新，总消息数: " + conversation.getTotalMessages());
            }
            
        } catch (Exception e) {
            System.err.println("❌ saveMessagesToDatabase异常: " + e.getMessage());
            e.printStackTrace();
            throw e; // 重新抛出异常，让上层处理
        }
    }
    
    /**
     * 等待用户WebSocket连接建立
     * @param taskId 任务ID
     * @param userId 用户ID
     * @return 是否成功建立连接
     */
    private boolean waitForWebSocketConnection(String taskId, String userId) {
        System.out.println("🔄 等待用户WebSocket连接建立: taskId=" + taskId + ", userId=" + userId);
        
        int maxWaitTime = 5000; // 最大等待5秒
        int checkInterval = 100; // 每100ms检查一次
        int waitTime = 0;
        
        while (waitTime < maxWaitTime) {
            if (webSocketHandler.hasActiveUserSession(userId)) {
                System.out.println("✅ 用户WebSocket连接已建立，开始处理任务: taskId=" + taskId + ", userId=" + userId);
                return true;
            }
            
            try {
                Thread.sleep(checkInterval);
                waitTime += checkInterval;
                
                // 每秒输出一次等待状态
                if (waitTime % 1000 == 0) {
                    System.out.println("⏳ 继续等待用户WebSocket连接... (已等待" + (waitTime/1000) + "秒): taskId=" + taskId + ", userId=" + userId);
                }
                
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.err.println("⚠️ 用户WebSocket等待被中断: taskId=" + taskId + ", userId=" + userId);
                return false;
            }
        }
        
        System.err.println("⏰ 用户WebSocket连接等待超时(" + (maxWaitTime/1000) + "秒): taskId=" + taskId + ", userId=" + userId);
        return false;
    }
    
    /**
     * 保存用户音频文件
     */
    private String saveUserAudioFile(String audioData, String format, Long userId) {
        try {
            // 使用VoiceFileStorageService保存用户录音文件
            return voiceFileStorageService.storeVoiceFile(audioData, format, userId);
        } catch (Exception e) {
            System.err.println("❌ 保存用户音频文件失败: " + e.getMessage());
            throw new RuntimeException("保存用户音频文件失败: " + e.getMessage(), e);
        }
    }
}
